package com.cy.cur.aqs;

import org.testng.annotations.Test;

import java.sql.Time;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

public class AQS_DEMO1 {

    @Test
    public void t1() throws InterruptedException {
        Thread thread = new Thread(() -> {
            System.out.println("线程即将阻塞");
            LockSupport.park(); // 等待许可证
            System.out.println("线程被唤醒");
            System.out.println("线程即将阻塞2");
            LockSupport.park(); // 等待许可证
            System.out.println("线程被唤醒2");
        });
        thread.start();

        Thread.sleep(2000);
        System.out.println("发放许可证，唤醒线程");
        LockSupport.unpark(thread);
        Thread.sleep(2000);
        System.out.println("发放许可证，唤醒线程");
        LockSupport.unpark(thread);
    }

    @Test
    public void t2() throws InterruptedException {
        Thread thread = new Thread(() -> {
            System.out.println("线程即将阻塞");
            LockSupport.parkNanos(2_000_000_000); // 等待许可证 2s 不管有没有 许可证都结束
            System.out.println("线程被唤醒");
        });
        thread.start();
        Thread.sleep(5000);
        System.out.println("主线程结束");
    }

    @Test
    public void t3() throws InterruptedException {
        Thread thread = new Thread(() -> {
            System.out.println("线程即将阻塞");
            LockSupport.parkUntil(System.currentTimeMillis() + 2000); // 等待许可证 2s 不管有没有 许可证都结束
            System.out.println("线程被唤醒");
        });
        thread.start();
        Thread.sleep(5000);
        System.out.println("主线程结束");
    }

    @Test
    public void t4() throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                LockSupport.park(); // 阻塞，响应中断
                System.out.println("唤醒或中断");
            }
        });
        thread.start();
        Thread.sleep(5000);
        thread.interrupt(); // 中断会触发 park() 返回
    }

    @Test
    public void t4_1() throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (true) {
                System.out.println("线程上锁");
                LockSupport.park(); // 阻塞，响应中断
                System.out.println("线程解锁");
            }
        });
        thread.start();
        Thread.sleep(3000);
        thread.interrupt(); // 中断会触发 park() 返回
        System.out.println("中断命令");
    }

    @Test
    public void t4_2() throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (true) {
                System.out.println("线程上锁");
                LockSupport.park(); // 阻塞，响应中断
                System.out.println("线程解锁");

                if (Thread.interrupted()) {
                    System.out.println("线程被中断了 的结束了");
                }
            }
        });
        thread.start();
        Thread.sleep(3000);
        thread.interrupt(); // 中断会触发 park() 返回
        System.out.println("中断命令");
    }


    private volatile int num = 0;

    @Test
    public void t5() throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(1000);
        for (int i = 0; i < 1000; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    ++num;
                    try {
                        TimeUnit.MILLISECONDS.sleep(5);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    countDownLatch.countDown();
                }
            }).start();
        }
        countDownLatch.await();
        System.out.println(num);
    }

    @Test
    public void t5_1() throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(1000);
        for (int i = 0; i < 1000; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (AQS_DEMO1.class) {
                        ++num;
                        try {
                            TimeUnit.MILLISECONDS.sleep(5);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                        countDownLatch.countDown();
                    }
                }
            }).start();
        }
        countDownLatch.await();
        System.out.println(num);
    }

    @Test
    public void t5_2() throws InterruptedException {
        ReentrantLock lock = new ReentrantLock();

        CountDownLatch countDownLatch = new CountDownLatch(1000);
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> {
                lock.lock();
                try {
                    ++num;
                    TimeUnit.MILLISECONDS.sleep(5);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                    lock.unlock();
                }
            }).start();
        }
        countDownLatch.await();
        System.out.println(num);
    }

}
